﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Arcadium.Audio
{
    class AudioManager : DrawableGameComponent
    {
        // TODO: Debug
        private static bool MUSIC_ENABLED = false;

        private static Random random = new Random();

        private static bool BackgroundMusicIsPlaying = false;
        private static bool MusicStartIsRequested = false;
        private static List<Song> tracks = new List<Song>();
        private static List<int> trackRandomIndex = new List<int>();
        private static int trackIndex = -1;

        public static SoundEffect MenuChangeItem { get; private set; }
        public static SoundEffect MenuForward { get; private set; }
        public static SoundEffect MenuBack { get; private set; }

        public static SoundEffect Jump { get; private set; }
        public static SoundEffect HandGun { get; private set; }
        public static SoundEffect Crate { get; private set; }
        public static SoundEffect GameOver { get; private set; }

        public static SoundEffect SmallEnemyDeath { get; private set; }
        public static SoundEffect BigEnemyDeath { get; private set; }
        public static SoundEffect GhostEnemyDeath { get; private set; }

        public static SoundEffect BigStomp { get; private set; }
        public static SoundEffect ZombieMode { get; private set; }


        AudioManager(Game game)
            : base(game)
        { }

        protected override void LoadContent()
        {
            MediaPlayer.IsRepeating = false;

            #region Load soundtrack

            int nTracks = 6;
            tracks = new List<Song>(nTracks);

            string[] trackStrings = new string[]{ 
                "Audio\\01. Title Screen",
                "Audio\\02. Tutorial",
                "Audio\\03. Construction Yard",
                "Audio\\04. Rocket Silo",
                "Audio\\05. Moon Temple",
                "Audio\\06. Radical Fishing OST",
            };
            foreach (var trackString in trackStrings)
            {
                tracks.Add(Game.Content.Load<Song>(trackString));
                int tempIndex;
                while (trackRandomIndex.Contains(tempIndex = random.Next(nTracks))) ;
                trackRandomIndex.Add(tempIndex);
            }

            #endregion

            #region Load soundeffects

            MenuChangeItem = Game.Content.Load<SoundEffect>("Audio\\Soundeffects\\menuchangeitem");
            MenuForward = Game.Content.Load<SoundEffect>("Audio\\Soundeffects\\menuforward");
            MenuBack = Game.Content.Load<SoundEffect>("Audio\\Soundeffects\\menuback");

            Jump = Game.Content.Load<SoundEffect>("Audio\\Soundeffects\\Gameplay\\jump");
            HandGun = Game.Content.Load<SoundEffect>("Audio\\Soundeffects\\Gameplay\\handgun");
            Crate = Game.Content.Load<SoundEffect>("Audio\\Soundeffects\\Gameplay\\crate");
            GameOver = Game.Content.Load<SoundEffect>("Audio\\Soundeffects\\Gameplay\\gameover");

            SmallEnemyDeath = Game.Content.Load<SoundEffect>("Audio\\Soundeffects\\Gameplay\\smallEnemyDeath");
            BigEnemyDeath = Game.Content.Load<SoundEffect>("Audio\\Soundeffects\\Gameplay\\bigEnemyDeath");
            GhostEnemyDeath = Game.Content.Load<SoundEffect>("Audio\\Soundeffects\\Gameplay\\ghostEnemyDeath");

            BigStomp = Game.Content.Load<SoundEffect>("Audio\\Soundeffects\\Gameplay\\bigStomp");
            ZombieMode = Game.Content.Load<SoundEffect>("Audio\\Soundeffects\\Gameplay\\zombieMode");

            #endregion

            if (MediaPlayer.GameHasControl && MUSIC_ENABLED)
            {
                BackgroundMusicIsPlaying = true;
                StartMusic();
            }
        }

        /// <summary>
        /// Creates a new NetworkSessionComponent.
        /// </summary>
        public static void Create(Game game)
        {
            // Create a MusicControllerComponent, and add it to the Game.
            game.Components.Add(new AudioManager(game));
        }

        /// <summary>
        /// Shuts down the component.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                Game.Components.Remove(this);
            }
            base.Dispose(disposing);
        }

        public override void Update(GameTime gameTime)
        {
            if (MediaPlayer.GameHasControl && MUSIC_ENABLED)
            {
                if (!MusicStartIsRequested && BackgroundMusicIsPlaying &&
                    MediaPlayer.State == MediaState.Stopped)
                {
                    trackIndex++;
                    if (trackIndex == trackRandomIndex.Count)
                        trackIndex = 0;
                    MediaPlayer.Play(tracks[trackRandomIndex[trackIndex]]);
                    MusicStartIsRequested = true;
                }
                if (BackgroundMusicIsPlaying &&
                    MediaPlayer.State == MediaState.Playing)
                {
                    MusicStartIsRequested = false;
                }
            }
            else
            {
                MusicStartIsRequested = false;
            }
        }
        
        private void StartMusic()
        {
            if (!MUSIC_ENABLED)
                return;

            trackIndex++;
            if (trackIndex == trackRandomIndex.Count)
                trackIndex = 0;
            MediaPlayer.Play(tracks[trackRandomIndex[trackIndex]]);
            MusicStartIsRequested = true;
        }

        internal static void PlaySong(int index)
        {
            if (!MUSIC_ENABLED)
                return;

            MediaPlayer.Play(tracks[index]);
            MusicStartIsRequested = true;
        }
    }
}